package com.xbongbong.paas.enums;

import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.pro.enums.fund.enums.PayMethodDistributorEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import lombok.Getter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 回款单、付款单、其他收入单、其他支出单 类型总枚举
 * @author zcp
 * @version v1.0
 * @since v1.0
 */
@Getter
public enum SheetTypeEnum {
    //--------------------------- 回款单相关类型 ---------------------------
    /**
     * 回款单-已核销
     * 既有回款金额，又有核销金额
     */
    WRITE_OFF("1", "writeOff", "enum.sheetTypeEnum.name.write_off", "enum.sheetTypeEnum.formName.write_off", "enum.sheetTypeEnum.memo.write_off", XbbRefTypeEnum.PAYMENT_SHEET.getCode(), XbbRefTypeEnum.PAYMENT_SHEET),

    /**
     * 回款单-预收款核销
     * 只有核销金额
     */
    WRITE_OFF_PREPAYMENT("2", "writeOffPrepayment", "enum.sheetTypeEnum.name.write_off_prepayment", "enum.sheetTypeEnum.formName.write_off_prepayment", "enum.sheetTypeEnum.memo.write_off_prepayment", XbbRefTypeEnum.WRITE_OFF_PREPAYMENT.getCode(), XbbRefTypeEnum.PAYMENT_SHEET),

    /**
     * 回款单-预收款
     * 只有回款金额
     */
    PREPAYMENT("3", "prepayment", "enum.sheetTypeEnum.name.prepayment", "enum.sheetTypeEnum.formName.prepayment", "enum.sheetTypeEnum.memo.prepayment", XbbRefTypeEnum.PREPAYMENT.getCode(), XbbRefTypeEnum.PAYMENT_SHEET),

    /**
     * 回款单-红冲已核销
     * 既有回款金额，又有核销金额
     */
    RED_WRITE_OFF("4", "redWriteOff", "enum.sheetTypeEnum.name.red_write_off", "enum.sheetTypeEnum.formName.red_write_off", "enum.sheetTypeEnum.memo.red_write_off", XbbRefTypeEnum.RED_PAYMENT_SHEET.getCode(), XbbRefTypeEnum.PAYMENT_SHEET),
    /**
     * 回款单-红冲预收款核销
     * 既有回款金额，又有核销金额
     */
    RED_WRITE_OFF_PREPAYMENT("5", "redWriteOffPrepayment", "enum.sheetTypeEnum.name.red_write_off_prepayment", "enum.sheetTypeEnum.formName.red_write_off_prepayment", "enum.sheetTypeEnum.memo.red_write_off_prepayment", XbbRefTypeEnum.RED_WRITE_OFF_PREPAYMENT.getCode(), XbbRefTypeEnum.PAYMENT_SHEET),
    /**
     * 回款单-红冲预收款核销(退到余额)
     * 只有核销金额
     */
    RED_WRITE_OFF_BALANCE("8", "redWriteOffBalance", "enum.sheetTypeEnum.name.red_write_off_balance", "enum.sheetTypeEnum.formName.red_write_off_balance", "enum.sheetTypeEnum.memo.red_write_off_balance", XbbRefTypeEnum.RED_WRITE_OFF_BALANCE.getCode(), XbbRefTypeEnum.PAYMENT_SHEET),
    /**
     * 回款单-红冲预收款余额
     * 只有回款金额
     */
    RED_PREPAYMENT("6", "redPrepayment", "enum.sheetTypeEnum.name.red_prepayment", "enum.sheetTypeEnum.formName.red_prepayment", "enum.sheetTypeEnum.memo.red_prepayment", XbbRefTypeEnum.RED_PREPAYMENT.getCode(), XbbRefTypeEnum.PAYMENT_SHEET),

    /**
     * 回款单-坏账
     * 既有回款金额，又有核销金额
     */
    BAD_PAYMENT("7", "badPayment", "enum.sheetTypeEnum.name.bad_payment", "enum.sheetTypeEnum.formName.bad_payment", "enum.sheetTypeEnum.memo.bad_payment", XbbRefTypeEnum.BAD_DEBT.getCode(), XbbRefTypeEnum.PAYMENT_SHEET),

    //--------------------------- 付款单相关类型 ---------------------------
    /**
     * 付款单的类型
     */
    /**
     * 付款单-已核销
     * 既有付款金额，又有核销金额
     */
    WRITE_OFF_PAY("1", "writeOffPay", "enum.sheetTypeEnum.name.write_off_pay", "enum.sheetTypeEnum.formName.write_off_pay", "enum.sheetTypeEnum.memo.write_off_pay", XbbRefTypeEnum.PAY_SHEET.getCode(), XbbRefTypeEnum.PAY_SHEET),

    /**
     * 付款单-预付款核销
     * 只有核销金额
     */
    WRITE_OFF_PREPAY("2", "writeOffPrepay", "enum.sheetTypeEnum.name.write_off_prepay", "enum.sheetTypeEnum.formName.write_off_prepay", "enum.sheetTypeEnum.memo.write_off_prepay", XbbRefTypeEnum.WRITE_OFF_PREPAY.getCode(), XbbRefTypeEnum.PAY_SHEET),

    /**
     * 付款单-预付款
     * 只有付款金额
     */
    PREPAY("3", "prepay", "enum.sheetTypeEnum.name.prepay", "enum.sheetTypeEnum.formName.prepay", "enum.sheetTypeEnum.memo.prepay", XbbRefTypeEnum.PREPAY.getCode(), XbbRefTypeEnum.PAY_SHEET),

    /**
     * 付款单-红冲已核销
     * 既有付款金额，又有核销金额
     */
    RED_WRITE_OFF_PAY("4", "redWriteOffPay", "enum.sheetTypeEnum.name.red_write_off_pay", "enum.sheetTypeEnum.formName.red_write_off_pay", "enum.sheetTypeEnum.memo.red_write_off_pay", XbbRefTypeEnum.RED_WRITE_OFF_PAY.getCode(), XbbRefTypeEnum.PAY_SHEET),
    /**
     * 付款单-红冲预付款核销
     * 既有付款金额，又有核销金额
     */
    RED_WRITE_OFF_PREPAY("5", "redWriteOffPrepay", "enum.sheetTypeEnum.name.red_write_off_prepay", "enum.sheetTypeEnum.formName.red_write_off_prepay", "enum.sheetTypeEnum.memo.red_write_off_prepay", XbbRefTypeEnum.RED_WRITE_OFF_PREPAY.getCode(), XbbRefTypeEnum.PAY_SHEET),
    /**
     * 付款单-红冲预付款余额
     * 只有回款金额
     */
    RED_PREPAY("6", "redPrepay", "enum.sheetTypeEnum.name.red_prepay", "enum.sheetTypeEnum.formName.red_prepay", "enum.sheetTypeEnum.memo.red_prepay", XbbRefTypeEnum.RED_PREPAY.getCode(), XbbRefTypeEnum.PAY_SHEET),

    /**
     * 付款单-坏账
     * 既有付款金额，又有核销金额
     */
    BAD_PAY("7", "badPay", "enum.sheetTypeEnum.name.bad_pay", "enum.sheetTypeEnum.formName.bad_pay", "enum.sheetTypeEnum.memo.bad_pay", XbbRefTypeEnum.BAD_PAY.getCode(), XbbRefTypeEnum.PAY_SHEET),

    //--------------------------- 其他收入单相关类型 ---------------------------
    /**
     * 其他收入单-已收款
     */
    OTHER_INCOME("1", XbbRefTypeEnum.OTHER_INCOME.getAlias(), "enum.sheetTypeEnum.name.other_income", "enum.sheetTypeEnum.formName.other_income", "enum.sheetTypeEnum.memo.other_income", XbbRefTypeEnum.OTHER_INCOME.getCode(), XbbRefTypeEnum.OTHER_INCOME),
    /**
     * 其他收入单-红冲已收款
     */
    RED_OTHER_INCOME("2", "redOtherIncome", "enum.sheetTypeEnum.name.red_other_income", "enum.sheetTypeEnum.formName.red_other_income", "enum.sheetTypeEnum.memo.red_other_income", XbbRefTypeEnum.RED_OTHER_INCOME.getCode(), XbbRefTypeEnum.OTHER_INCOME),

    //--------------------------- 其他支出单相关类型 ---------------------------
    /**
     * 其他支出单-已付款
     */
    OTHER_EXPENSE("1", XbbRefTypeEnum.OTHER_EXPENSE.getAlias(), "enum.sheetTypeEnum.name.other_expense", "enum.sheetTypeEnum.formName.other_expense", "enum.sheetTypeEnum.memo.other_expense", XbbRefTypeEnum.OTHER_EXPENSE.getCode(), XbbRefTypeEnum.OTHER_EXPENSE),
    /**
     * 其他支出单-红冲已付款
     */
    RED_OTHER_EXPENSE("2", "redOtherExpense", "enum.sheetTypeEnum.name.red_other_expense", "enum.sheetTypeEnum.formName.red_other_expense", "enum.sheetTypeEnum.memo.red_other_expense", XbbRefTypeEnum.RED_OTHER_EXPENSE.getCode(), XbbRefTypeEnum.OTHER_EXPENSE),

    /**
     * 未知
     */
    UNKNOWN("404", XbbRefTypeEnum.UNKNOWN.getAlias(), XbbRefTypeEnum.UNKNOWN.getName(), XbbRefTypeEnum.UNKNOWN.getName(), "", XbbRefTypeEnum.UNKNOWN.getCode(), XbbRefTypeEnum.UNKNOWN),
    ;


    /**
     * 类型code值
     */
    private String code;

    /**
     * 类型名称
     */
    private String name;

    /**
     * 类型attr
     */
    private String alias;

    /**
     * 类型名称，比如四种红冲的统一为红冲回款单
     */
    private String formName;

    /**
     * 解释
     */
    private String memo;

    /**
     * 业务code，对应每个类型的业务code（XbbRefTypeEnum内的code值）
     */
    private Integer businessType;

    /**
     * 该类型属于哪个业务，回款单or付款单
     */
    private XbbRefTypeEnum xbbRefTypeEnum;

    SheetTypeEnum(String code, String alias, String name, String formName, String memo, Integer businessType, XbbRefTypeEnum xbbRefTypeEnum) {
        this.code = code;
        this.alias = alias;
        this.name = name;
        this.formName = formName;
        this.memo = memo;
        this.businessType = businessType;
        this.xbbRefTypeEnum = xbbRefTypeEnum;
    }
    /**
     * 根据不同类型对应的businessType判断得到其对应的回款、付款、其他收入、其他支出单本质的业务类型
     * @param businessType 业务类型businessType
     * @return com.xbongbong.paas.enums.SheetTypeEnum
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static SheetTypeEnum getByBusinessType(Integer businessType) {
        if (Objects.equals(businessType, XbbRefTypeEnum.PREPAYMENT_BALANCE.getCode())) {
            //如果是预收款列表类型，则也返回预收款枚举：预收款余额是一个单独的列表，有自己的XbbRefTypeEnum，但是其本质还是预收款类型
            return PREPAYMENT;
        }else if (Objects.equals(businessType, XbbRefTypeEnum.PREPAY_BALANCE.getCode())) {
            //如果是预付款列表类型，则也返回预付款枚举：预付款余额是一个单独的列表，有自己的XbbRefTypeEnum，但是其本质还是预付款类型
            return PREPAY;
        }
        for (SheetTypeEnum cacheCode : values()) {
            if (Objects.equals(businessType, cacheCode.getBusinessType())) {
                return cacheCode;
            }
        }
        return UNKNOWN;
    }

    /**
     * 判断是否是回款、付款、其他收入、其他支出单
     * @param sheetTypeEnum 回款、付款、其他收入、其他支出单 类型总枚举
     * @return boolean true 创建/编辑回款、付款、其他收入、其他支出单，false 不是任何一种回款、付款、其他收入、其他支出单业务
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean validateSheet(SheetTypeEnum sheetTypeEnum) {
        return sheetTypeEnum != null && !Objects.equals(sheetTypeEnum, UNKNOWN);
    }

    /**
     * 判断是否是回款、付款单
     * @param sheetTypeEnum 回款、付款类型总枚举
     * @return boolean true 创建/编辑回款、付款单，false 不是任何一种回款、付款单业务
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean validatePay(SheetTypeEnum sheetTypeEnum) {
        return sheetTypeEnum != null && (Objects.equals(sheetTypeEnum.getXbbRefTypeEnum(), XbbRefTypeEnum.PAYMENT_SHEET) || Objects.equals(sheetTypeEnum.getXbbRefTypeEnum(), XbbRefTypeEnum.PAY_SHEET));
    }

    /**
     * 通过类型code及xbbRefTypeEnum得到具体的回/付款单类型（回款单、付款单同样类型的code是一致的，因此还需要xbbRefTypeEnum来进一步区分是哪种业务的类型）
     * @param code 单据类型
     * @param xbbRefTypeEnum 回款单or付款单业务类型
     * @return com.xbongbong.paas.enums.SheetTypeEnum
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static SheetTypeEnum getByCodeRefTypeEnum(String code, XbbRefTypeEnum xbbRefTypeEnum){
        return getByCodeRefType(code, xbbRefTypeEnum.getCode());
    }
    /**
     * 通过类型code及xbbRefTypeEnum得到具体的回/付款单类型（回款单、付款单同样类型的code是一致的，因此还需要xbbRefTypeEnum来进一步区分是哪种业务的类型）
     * @param code 单据类型
     * @param xbbRefType 回款单or付款单业务类型code
     * @return com.xbongbong.paas.enums.SheetTypeEnum
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static SheetTypeEnum getByCodeRefType(String code, Integer xbbRefType){
        for (SheetTypeEnum cacheCode : values()) {
            if (Objects.equals(code, cacheCode.getCode()) && Objects.equals(xbbRefType, cacheCode.xbbRefTypeEnum.getCode())) {
                return cacheCode;
            }
        }
        return UNKNOWN;
    }


    /**
     * 判断是否是预收款核销
     * @param sheetType
     * @return boolean
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean checkWriteOffPrepayment(String sheetType){
        //判断是否是预收款核销，比如只有预收款核销详情页有，红冲(退到余额)按钮
        return Objects.equals(sheetType, WRITE_OFF_PREPAYMENT.code);
    }
    /**
     * 判断是否只有核销金额字段
     * @param sheetType
     * @return boolean
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean onlyWriteOffAmount(String sheetType){
        //判断是否是预收款核销、红冲预收款核销(退到余额)，因为这两种是只有核销金额
        return Objects.equals(sheetType, WRITE_OFF_PREPAYMENT.code) || Objects.equals(sheetType, RED_WRITE_OFF_BALANCE.code) || Objects.equals(sheetType, WRITE_OFF_PREPAY.code);
    }
    /**
     * 根据回/付款单类型判断是否为预收款核销 or 预付款核销
     * @param sheetTypeEnum 回/付款单类型
     * @return boolean true代表预收款核销 or 预付款核销
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean isWriteOffPre(SheetTypeEnum sheetTypeEnum) {
        //是否为预收款核销 or 预付款核销
        return Objects.equals(sheetTypeEnum, WRITE_OFF_PREPAYMENT) || Objects.equals(sheetTypeEnum, WRITE_OFF_PREPAY);
    }
    /**
     * 根据回/付款单/其他收入单/其他支出单类型判断是否为红冲类型
     * @param sheetTypeEnum 类型
     * @return boolean true红冲
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean isRed(SheetTypeEnum sheetTypeEnum) {
        //判断包含了crm部分回款单的几个红冲类型，及进销存部分付款单的几个红冲类型
        return Objects.equals(sheetTypeEnum, RED_PREPAYMENT) || Objects.equals(sheetTypeEnum, RED_WRITE_OFF_PREPAYMENT) || Objects.equals(sheetTypeEnum, RED_WRITE_OFF) || Objects.equals(sheetTypeEnum, RED_PREPAY) || Objects.equals(sheetTypeEnum, RED_WRITE_OFF_PREPAY) || Objects.equals(sheetTypeEnum, RED_WRITE_OFF_PAY) || Objects.equals(sheetTypeEnum, RED_OTHER_INCOME) || Objects.equals(sheetTypeEnum, RED_OTHER_EXPENSE);
    }

    /**
     * 根据回/付款单类型判断是否为坏账类型
     * @param sheetTypeEnum 回/付款单类型
     * @return boolean true坏账
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean isBad(SheetTypeEnum sheetTypeEnum) {
        //判断包含了回款单坏账、付款单坏账
        return Objects.equals(sheetTypeEnum, BAD_PAYMENT) || Objects.equals(sheetTypeEnum, BAD_PAY);
    }

    /**
     * 判断该回/付款单类型是否有归属人
     * @param sheetTypeEnum 单据类型
     * @return boolean true 无归属人
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean noBelong(SheetTypeEnum sheetTypeEnum) {
        /*
          无归属人的回款单类型有：预收款 or 红冲预收款余额
          无归属人的付款单类型有：预付款 or 红冲预付款余额
         */
        return Objects.equals(sheetTypeEnum, PREPAYMENT) || Objects.equals(sheetTypeEnum, RED_PREPAYMENT) || Objects.equals(sheetTypeEnum, PREPAY) || Objects.equals(sheetTypeEnum, RED_PREPAY);
    }
    /**
     * 根据回/付款单类型判断是否可以新建发票
     *
     * @param type 回/付款单类型
     * @return boolean
     * @author zcp
     * @since v1.0
     */
    public static boolean ifNewInvoice(String type){
        //只有已核销、预收/付款才能新建发票
        return Objects.equals(type, WRITE_OFF.code) || Objects.equals(type, PREPAYMENT.code) || Objects.equals(type, WRITE_OFF_PAY.code) || Objects.equals(type, PREPAY.code);
    }

    /**
     * 根据回款单/付款单类型获取跟预收款相关的类型
     * @param businessTypeEnum
     * @return
     */
    public static List<String> belongPrepay(XbbRefTypeEnum businessTypeEnum){
        List<String> typeList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        switch (businessTypeEnum){
            case PAYMENT_SHEET:
                typeList = Arrays.asList(PREPAYMENT.code,RED_PREPAYMENT.code);
                break;
            case PAY_SHEET:
                typeList = Arrays.asList(PREPAY.code,RED_PREPAY.code);
                break;
            default:
                break;
        }
        return typeList;
    }

    /**
     * 根据回款单/付款单类型获取除预收款相关的类型
     * @param businessTypeEnum
     * @return
     */
    public static List<String> belongOther(XbbRefTypeEnum businessTypeEnum){
        List<String> typeList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        switch (businessTypeEnum){
            case PAYMENT_SHEET:
                typeList = Arrays.asList(WRITE_OFF.code,WRITE_OFF_PREPAYMENT.code,RED_WRITE_OFF.code,RED_WRITE_OFF_PREPAYMENT.code,RED_WRITE_OFF_BALANCE.code,BAD_PAYMENT.code);
                break;
            case PAY_SHEET:
                typeList = Arrays.asList(WRITE_OFF_PAY.code,WRITE_OFF_PREPAY.code,RED_WRITE_OFF_PAY.code,RED_WRITE_OFF_PREPAY.code,BAD_PAY.code);
                break;
            default:
                break;
        }
        return typeList;
    }

    public static Integer getByCode(String code, Integer businessType) {
        if (Objects.equals(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), businessType)) {
            for (SheetTypeEnum item : getPaymentSheetList()) {
                if (Objects.equals(item.getCode(), code)) {
                   return item.getBusinessType();
                }
            }
        } else if (Objects.equals(XbbRefTypeEnum.PAY_SHEET.getCode(), businessType)) {
            for (SheetTypeEnum item : getPaySheetList()) {
                if (Objects.equals(item.getCode(), code)) {
                    return item.getBusinessType();
                }
            }
        }
        return businessType;
    }

    public static List<SheetTypeEnum> getPaymentSheetList() {
        return Arrays.asList(WRITE_OFF,WRITE_OFF_PREPAYMENT,PREPAYMENT, RED_WRITE_OFF,RED_WRITE_OFF_PREPAYMENT, RED_PREPAYMENT, BAD_PAYMENT);
    }

    public static List<SheetTypeEnum> getPaySheetList() {
        return Arrays.asList(WRITE_OFF_PAY,WRITE_OFF_PREPAY,PREPAY, RED_WRITE_OFF_PAY,RED_WRITE_OFF_PREPAY,RED_PREPAY, BAD_PAY);
    }

    /**
     * 获取经销商类型回款单厂商端代客操作的默认支付方式
     *      代客操作：已核销，预收款
     *      预收款账户：预收款核销，红冲预收款核销（退到余额）
     *      线下打款：红冲预收款核销（原Pro的），红冲预收款余额
     *      另外，红冲已核销与原单一致（关联新建时处理好）
     * @param sheetType
     * @return java.lang.String
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static String getDefaultPayMethod4Distributor(String sheetType){
        if (Objects.equals(sheetType, WRITE_OFF.code) || Objects.equals(sheetType, PREPAYMENT.code)) {
            //代客操作：已核销，预收款
            return PayMethodDistributorEnum.PRO_OPERATE.getCode();
        } else if (Objects.equals(sheetType, WRITE_OFF_PREPAYMENT.code) || Objects.equals(sheetType, RED_WRITE_OFF_BALANCE.code)) {
            //预收款账户：预收款核销，红冲预收款核销（退到余额）
            return PayMethodDistributorEnum.PREPAYMENT.getCode();
        } else if (Objects.equals(sheetType, RED_WRITE_OFF_PREPAYMENT.code) || Objects.equals(sheetType, RED_PREPAYMENT.code)) {
            //线下打款：红冲预收款核销（原Pro的），红冲预收款余额
            return PayMethodDistributorEnum.OFFLINE.getCode();
        }
        return "";
    }

    /**
     * 判断该类型是否影响资金账户
     * 注：坏账，预收款核销，红冲预收款核销(退到余额)不影响资金账户
     * @param sheetType
     * @return boolean
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean effectFundAccount(String sheetType){
        return !Objects.equals(sheetType, BAD_PAYMENT.getCode()) && !Objects.equals(sheetType, WRITE_OFF_PREPAYMENT.getCode()) && !Objects.equals(sheetType, RED_WRITE_OFF_BALANCE.code);
    }

    public String getName() {
        return I18nMessageUtil.getMessage(name);
    }
    public String getI18nName() {
        return name;
    }

    public String getFormName() {
        return I18nMessageUtil.getMessage(formName);
    }
    public String getI18nFormName() {
        return name;
    }

    public String getMemo() {
        return I18nMessageUtil.getMessage(memo);
    }
    public String getI18nMemo() {
        return name;
    }
}
